package com.platform.api;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Validator;
import com.jfinal.aop.Duang;
import com.jfinal.kit.HttpKit;
import com.jfinal.kit.Prop;
import com.jfinal.kit.StrKit;
import com.jfinal.weixin.sdk.api.ApiResult;
import com.jfinal.weixin.sdk.api.PaymentApi;
import com.jfinal.weixin.sdk.kit.IpKit;
import com.jfinal.weixin.sdk.kit.PaymentKit;
import com.jfinal.wxaapp.api.WxaTemplate;
import com.jfinal.wxaapp.api.WxaTemplateApi;
import com.platform.annotation.IgnoreAuth;
import com.platform.annotation.LoginUser;
import com.platform.config.IntegralType;
import com.platform.entity.*;
import com.platform.service.*;
import com.platform.util.ApiBaseAction;
import com.platform.util.wechat.WechatRefundApiResult;
import com.platform.util.wechat.WechatUtil;
import com.platform.utils.ResourceUtil;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.math.BigDecimal;
import java.util.*;

import static com.platform.config.Constants.PurchaseSuccessNotice;
import static com.platform.util.CommonUtil.getProp;
import static com.platform.util.wechat.WechatUtil.setWxaConfig;

/**
 * 作者: @author Harmon <br>
 * 时间: 2017-08-11 08:32<br>
 * 描述: ApiIndexController <br>
 */
@RestController
@RequestMapping("/api/pay")
public class ApiPayController extends ApiBaseAction {
    private Logger logger = Logger.getLogger(getClass());
    @Autowired
    private ApiOrderService orderService;
    @Autowired
    private ApiOrderGoodsService orderGoodsService;
    @Autowired
    private ApiGoodsService goodsService;
    @Autowired
    private ApiProductService productService;
    @Autowired
    private ApiUserIntegralService integralService;
    @Autowired
    private ApiUserService apiUserService;

    static Prop prop = getProp();
    String appid = prop.get("payAppId");
    String partner = prop.get("payMchId");
    String paternerKey = prop.get("payPaternerKey");
    String notify_url = prop.get("payCallBackDomain") + "/api/pay/pay_notify";
    String refund_url = prop.get("payCallBackDomain") + "/api/pay/refund_notify";
    String certPath = ResourceUtil.getConfigByName("wx.certName");

    /**
     * 申请微信退款
     */
//    @IgnoreAuth
//    @RequestMapping("applyWxRefund")
//    public Map applyWxRefund(String out_trade_no, String orderMoney, String refundMoney) {
//
//        System.out.println(String.valueOf((Float.valueOf(orderMoney) * 100)));
//        Map<String, String> params = new HashMap<>();
//        params.put("appid", appid);//公众账号ID
//        params.put("mch_id", partner);//商户号
//        params.put("out_trade_no", out_trade_no);
//        params.put("out_refund_no", System.currentTimeMillis() + "");//商户订单号
//        params.put("total_fee", String.valueOf((((int) (Float.valueOf(orderMoney) * 100)))));//订单金额
//        params.put("refund_fee", String.valueOf((((int) (Float.valueOf(refundMoney) * 100)))));//退款金额
//        params.put("notify_url", refund_url);//退款结果通知url
//        Map<String, String> refund = PaymentApi.refund(params, paternerKey, certPath);
//        String result_code = refund.get("result_code");
//        System.out.println("result_code" + result_code);
//        return refund;
//    }

    /**
     * 微信小程序支付：统一下单接口
     */
    @RequestMapping("WeChatPay")
    public Object WeChatPay(@LoginUser UserVo loginUser, @RequestParam Integer orderId, HttpServletRequest request) {

        // openId，采用 网页授权获取 access_token API：SnsAccessTokenApi获取
        String openId = loginUser.getWeixin_openid();

        if (Validator.isEmpty(openId)) {
            return toResponsFail("请先授权登录");
        }

        OrderVo orderVo = orderService.queryObject(orderId);
        if (Validator.isEmpty(orderVo)) {
            return toResponsFail("订单不存在");
        }

        if (orderVo.getPay_status() != 0) {
            return toResponsFail("订单已支付，请不要重复操作");
        }

        if (orderVo.getOrder_status() == 101) {
            return toResponsFail("订单已取消，不能支付");
        }

        BigDecimal actual_price = orderVo.getActual_price();

        if (Validator.isEmpty(actual_price)) {
            return toResponsFail("无法获取订单实际要支付的价格");
        }

        String total_fee = actual_price.toString();

        // 统一下单文档地址：https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1
        Map<String, String> params = new HashMap<String, String>();
        params.put("appid", appid);
        params.put("mch_id", partner);
        Map<String, Object> orderGoodsParam = new HashMap<>();
        orderGoodsParam.put("order_id", orderId);
        //订单的商品
        List<OrderGoodsVo> orderGoods = orderGoodsService.queryList(orderGoodsParam);
        if (null == orderGoods) {
            return toResponsFail("无法获取订单中的物品");
        }
        String body = "种子生活";
//        for (OrderGoodsVo goodsVo : orderGoods) {
//            body = body + goodsVo.getGoods_name() + "、";
//        }
//        if (body.length() > 0) {
//            body = body.substring(0, body.length() - 1);
//        }
        // 商品描述
        params.put("body", body);
        String out_trade_no = System.currentTimeMillis() + "";
        params.put("out_trade_no", out_trade_no);
        int price = ((int) (Float.valueOf(total_fee) * 100));
        params.put("total_fee", price + "");
        params.put("attach", orderId.toString());

        String ip = IpKit.getRealIp(request);
        if (StrKit.isBlank(ip)) {
            ip = "127.0.0.1";
        } else {
            String[] split = ip.split(",");
            ip = split[0];
        }

        params.put("spbill_create_ip", ip);
        params.put("trade_type", PaymentApi.TradeType.JSAPI.name());
        params.put("nonce_str", System.currentTimeMillis() / 1000 + "");
        params.put("notify_url", notify_url);
        params.put("openid", openId);

        String sign = PaymentKit.createSign(params, paternerKey);

        params.put("sign", sign);

        String xmlResult = PaymentApi.pushOrder(params);

        System.out.println(xmlResult);

        Map<String, String> result = PaymentKit.xmlToMap(xmlResult);

        String return_code = result.get("return_code");
        String return_msg = result.get("return_msg");
        if (StrKit.isBlank(return_code) || !"SUCCESS".equals(return_code)) {
            return toResponsFail("支付失败," + "return_code:" + return_msg);
        }
        String result_code = result.get("result_code");
        if (StrKit.isBlank(result_code) || !"SUCCESS".equals(result_code)) {
            return toResponsFail("支付失败," + "result_code:" + return_msg);

        }

        // 以下字段在return_code 和result_code都为SUCCESS的时候有返回
        String prepay_id = result.get("prepay_id");

        logger.info("prepay_id:" + prepay_id);

        Map<String, String> packageParams = new HashMap<>();
        packageParams.put("appId", appid);
        packageParams.put("timeStamp", System.currentTimeMillis() / 1000 + "");
        packageParams.put("nonceStr", System.currentTimeMillis() + "");
        packageParams.put("package", "prepay_id=" + prepay_id);
        packageParams.put("signType", "MD5");

        String packageSign = PaymentKit.createSign(packageParams, paternerKey);
        packageParams.put("paySign", packageSign);

        //处理业务
        orderVo.setPay_id(prepay_id);
        orderVo.setOut_trade_no(out_trade_no);
        // 付款中
//        orderVo.setPay_status(1);
        orderService.update(orderVo);
        return toResponsSuccess(packageParams);
    }


    /**
     * 支付回调
     */
    @IgnoreAuth
    @RequestMapping("refund_notify")
    public Object refund_notify(HttpServletRequest request, HttpServletResponse response) {

        // 支付结果通用通知文档: https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_7
        String xmlMsg = HttpKit.readData(request);

        System.out.println("退款通知=" + xmlMsg);

        Map<String, String> params = PaymentKit.xmlToMap(xmlMsg);

        // 商户退款单号
        String out_refund_no = params.get("out_refund_no");

        // 商户订单号
        String out_trade_no = params.get("out_trade_no");

        String result_code = params.get("result_code");
        String openId = params.get("openid");
        // 微信支付订单号
        String transaction_id = params.get("transaction_id");

        // 注意重复通知的情况，同一订单号可能收到多次通知，请注意一定先判断订单状态
        // 避免已经成功、关闭、退款的订单被再次更新
        try {
            if (result_code.equalsIgnoreCase("FAIL")) {
                //订单编号
                logger.error("订单" + out_trade_no + "退款失败");
            } else if (result_code.equalsIgnoreCase("SUCCESS")) {
                //订单编号
                logger.info("订单:" + out_trade_no + "退款成功");
                // 业务处理
                OrderVo orderInfo = orderService.queryByOutTradeNo(out_trade_no);

//                if (orderInfo.getOrder_status() == 201) {
                //支付状态;0未付款;1付款中;2已付款;4退款
                orderInfo.setPay_status(4);
                if (orderInfo.getOrder_status() == 402) {
                    orderInfo.setShipping_status(4);
                }
                //403-退款成功
                orderInfo.setOrder_status(403);
                orderInfo.setOut_refund_no(out_refund_no);
                orderService.update(orderInfo);
                System.out.println("订单更新成功");

                //商品的销售量减1，库存加1
                Map<String, Object> orderGoodsParam = new HashMap<>();
                orderGoodsParam.put("order_id", orderInfo.getId());
                List<OrderGoodsVo> orderGoodsVoList = orderGoodsService.queryList(orderGoodsParam);
                if (orderGoodsVoList.size() > 0) {
                    for (OrderGoodsVo orderGoodsVo : orderGoodsVoList) {
                        //销售量加1
                        Integer goods_id = orderGoodsVo.getGoods_id();
                        GoodsVo goodsVo = goodsService.queryObject(goods_id);
                        if (goodsVo != null) {
                            goodsVo.setSell_volume(goodsVo.getSell_volume() - 1);
                            goodsService.update(goodsVo);
                        }

                        //产品库存减去1
                        Integer product_id = orderGoodsVo.getProduct_id();
                        ProductVo productItem = productService.queryObject(product_id);
                        if (productItem != null) {
                            productItem.setGoods_number(productItem.getGoods_number() + 1);
                            productService.update(productItem);
                        }
                    }
                }
                System.out.println("商品的销售量更新成功");

                //记录积分详情
                int integral = (int) orderInfo.getActual_price().floatValue();
                if (integral != 0) {
                    UserIntegralVo userIntegralVo = new UserIntegralVo();
                    userIntegralVo.setUserId(Integer.valueOf(orderInfo.getUser_id().toString()));
                    userIntegralVo.setOrderId(orderInfo.getId());
                    //状态:1-增加；2-减少(即使用)
                    userIntegralVo.setStatus(2);
                    userIntegralVo.setIntegral(integral);
                    IntegralType orderIntegralType = IntegralType.ORDER_REFUND_INTEGRAL_TYPE;
                    userIntegralVo.setRemark(orderIntegralType.getName());
                    userIntegralVo.setIntegralType(orderIntegralType.getIndex());
                    userIntegralVo.setAddTime(new Date());
                    integralService.save(userIntegralVo);
                    //汇总用户目前积分
                    integralService.calUserCurrentPoints(orderInfo.getUser_id(), 2, userIntegralVo.getIntegral());
                    System.out.println("积分记录成功");
                }


                //微信发送模板信息：购买成功通知
                    setWxaConfig();//小程序配置信息
//                    WxaTemplateApi wxaTemplateApi = Duang.duang(WxaTemplateApi.class);
//                    WxaTemplate template = new WxaTemplate();
//                    template.setForm_id(orderInfo.getPay_id());//支付的prepay_id
//                    template.setTouser(openId);//接收者（用户）的 openid
//                    template.setTemplate_id(PurchaseSuccessNotice);//购买成功通知的模板ID
//                    template.setPage("pages/orderDetail/orderDetail?orderId=" + orderInfo.getId());//小程序调转的页面:订单详情
//                    template.add("keyword1", DateUtil.formatDateTime(orderInfo.getAdd_time()));//购买时间
//                    OrderGoodsVo orderGoodsVo = orderGoodsVoList.get(0);
//                    String keyword2 = "";
//                    String keyword3 = "";
//                    if (orderGoodsVo != null) {
//                        keyword2 = orderGoodsVo.getGoods_name();
//                        keyword3 = orderGoodsVo.getRetail_price().toString();
//                    }
//                    template.add("keyword2", keyword2);//物品名称
//                    template.add("keyword3", keyword3);//购买价格
//                    template.add("keyword4", orderInfo.getActual_price().toString());//订单总价
//                    template.add("keyword5", orderInfo.getOrder_sn());//订单号
//                    String build = template.build();
//                    ApiResult send = wxaTemplateApi.send(build);
//                    Integer errorCode = send.getErrorCode();
//                    if (errorCode != 0) {
//                        System.out.println("模板发送失败信息：" + send.getErrorMsg());
//                    }
//                    System.out.println("模板信息发送成功");
//                }
            }

            Map<String, String> xml = new HashMap<>();
            xml.put("return_code", "SUCCESS");
            xml.put("return_msg", "OK");
            String toXml = PaymentKit.toXml(xml);

            response.reset();
            PrintWriter out = response.getWriter();
            out.write(toXml);
            out.flush();
            out.close();

        } catch (IOException e) {
            logger.error("回调失败");
            e.printStackTrace();
        }

        return toResponsFail("下单失败");
    }

    /**
     * 支付回调
     */
    @IgnoreAuth
    @RequestMapping("pay_notify")
    public Object pay_notify(HttpServletRequest request, HttpServletResponse response) {

        // 支付结果通用通知文档: https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_7
        String xmlMsg = HttpKit.readData(request);

        System.out.println("支付通知=" + xmlMsg);

        Map<String, String> params = PaymentKit.xmlToMap(xmlMsg);

        String appid = params.get("appid");
        // 商户号
        String mch_id = params.get("mch_id");
        String result_code = params.get("result_code");
        String openId = params.get("openid");
        // 交易类型
        String trade_type = params.get("trade_type");
        // 付款银行
        String bank_type = params.get("bank_type");
        // 总金额
        String total_fee = params.get("total_fee");
        // 现金支付金额
        String cash_fee = params.get("cash_fee");
        // 微信支付订单号
        String transaction_id = params.get("transaction_id");
        // 商户订单号
        String out_trade_no = params.get("out_trade_no");
        // 支付完成时间，格式为yyyyMMddHHmmss
        String time_end = params.get("time_end");

        ///////////////////////////// 以下是附加参数///////////////////////////////////

        String orderId = params.get("attach");
        String fee_type = params.get("fee_type");
        String is_subscribe = params.get("is_subscribe");
        String err_code = params.get("err_code");
        String err_code_des = params.get("err_code_des");

        // 注意重复通知的情况，同一订单号可能收到多次通知，请注意一定先判断订单状态
        // 避免已经成功、关闭、退款的订单被再次更新
        try {
            if (result_code.equalsIgnoreCase("FAIL")) {
                //订单编号
                logger.error("订单" + out_trade_no + "支付失败");
            } else if (result_code.equalsIgnoreCase("SUCCESS")) {
                //订单编号
                logger.info("订单:" + orderId + "支付成功");
                // 业务处理
                OrderVo orderInfo = orderService.queryObject(Integer.valueOf(orderId));
                if (orderInfo.getOrder_status() == 0) {
                    orderInfo.setPay_status(2);
                    orderInfo.setOrder_status(201);
                    orderInfo.setShipping_status(0);
                    orderInfo.setPay_time(new Date());
                    orderInfo.setTransaction_id(transaction_id);
                    orderService.update(orderInfo);
                    System.out.println("订单更新成功");

                    //商品的销售量加1，库存减1
                    Map<String, Object> orderGoodsParam = new HashMap<>();
                    orderGoodsParam.put("order_id", orderId);
                    List<OrderGoodsVo> orderGoodsVoList = orderGoodsService.queryList(orderGoodsParam);
                    if (orderGoodsVoList.size() > 0) {
                        for (OrderGoodsVo orderGoodsVo : orderGoodsVoList) {
                            //销售量加1
                            Integer goods_id = orderGoodsVo.getGoods_id();
                            GoodsVo goodsVo = goodsService.queryObject(goods_id);
                            if (goodsVo != null) {
                                goodsVo.setSell_volume(goodsVo.getSell_volume() + 1);
                                goodsService.update(goodsVo);
                            }

                            //产品库存减去1
                            Integer product_id = orderGoodsVo.getProduct_id();
                            ProductVo productItem = productService.queryObject(product_id);
                            if (productItem != null) {
                                productItem.setGoods_number(productItem.getGoods_number() - 1);
                                productService.update(productItem);
                            }

                            //判断能否升级会员
                            Integer isMemberLimit = goodsVo.getIsMemberLimit();
                            if (isMemberLimit != null && isMemberLimit == 1) {
                                apiUserService.updateUserMember(orderInfo.getUser_id(), 1);
                            }
                        }
                    }
                    System.out.println("商品的销售量更新成功");

                    //记录积分详情
                    int integral = (int) orderInfo.getActual_price().floatValue();
                    if (integral != 0) {
                        UserIntegralVo userIntegralVo = new UserIntegralVo();
                        userIntegralVo.setUserId(Integer.valueOf(orderInfo.getUser_id().toString()));
                        userIntegralVo.setOrderId(Integer.valueOf(orderId));
                        //状态:1-增加；2-减少(即使用)
                        userIntegralVo.setStatus(1);
                        userIntegralVo.setIntegral(integral);
                        IntegralType orderIntegralType = IntegralType.ORDER_INTEGRAL_TYPE;
                        userIntegralVo.setRemark(orderIntegralType.getName());
                        userIntegralVo.setIntegralType(orderIntegralType.getIndex());
                        userIntegralVo.setAddTime(new Date());
                        integralService.save(userIntegralVo);
                        //汇总用户目前积分
                        integralService.calUserCurrentPoints(orderInfo.getUser_id(), 1, userIntegralVo.getIntegral());
                        System.out.println("积分记录成功");
                    }


                    //微信发送模板信息：购买成功通知
                    setWxaConfig();//小程序配置信息
                    WxaTemplateApi wxaTemplateApi = Duang.duang(WxaTemplateApi.class);
                    WxaTemplate template = new WxaTemplate();
                    //支付的prepay_id
                    template.setForm_id(orderInfo.getPay_id());
                    //接收者（用户）的 openid
                    template.setTouser(openId);
                    //购买成功通知的模板ID
                    template.setTemplate_id(PurchaseSuccessNotice);
                    //小程序调转的页面:订单详情
                    template.setPage("pages/orderDetail/orderDetail?orderId=" + orderInfo.getId());
                    //购买时间
                    template.add("keyword1", DateUtil.formatDateTime(orderInfo.getAdd_time()));
                    OrderGoodsVo orderGoodsVo = orderGoodsVoList.get(0);
                    String keyword2 = "";
                    String keyword3 = "";
                    if (orderGoodsVo != null) {
                        keyword2 = orderGoodsVo.getGoods_name();
                        keyword3 = orderGoodsVo.getRetail_price().toString();
                    }
                    //物品名称
                    template.add("keyword2", keyword2);
                    //购买价格
                    template.add("keyword3", keyword3);
                    //订单总价
                    template.add("keyword4", orderInfo.getActual_price().toString());
                    //订单号
                    template.add("keyword5", orderInfo.getOrder_sn());
                    String build = template.build();
                    ApiResult send = wxaTemplateApi.send(build);
                    Integer errorCode = send.getErrorCode();
                    if (errorCode != 0) {
                        System.out.println("模板发送失败信息：" + send.getErrorMsg());
                    }
                    System.out.println("模板信息发送成功");
                }
            }

            Map<String, String> xml = new HashMap<>();
            xml.put("return_code", "SUCCESS");
            xml.put("return_msg", "OK");
            String toXml = PaymentKit.toXml(xml);

            response.reset();
            PrintWriter out = response.getWriter();
            out.write(toXml);
            out.flush();
            out.close();

        } catch (IOException e) {
            logger.error("回调失败");
            e.printStackTrace();
        }

        return toResponsFail("下单失败");
    }

    /**
     * 订单退款请求
     */
    @RequestMapping("refund")
    public Object refund(@LoginUser UserVo loginUser, Integer orderId) {
        //
        OrderVo orderInfo = orderService.queryObject(orderId);

        if (null == orderInfo) {
            return toResponsFail("订单已取消");
        }

        if (orderInfo.getOrder_status() == 401 || orderInfo.getOrder_status() == 402) {
            return toResponsFail("订单已退款");
        }

        if (orderInfo.getPay_status() != 2) {
            return toResponsFail("订单未付款，不能退款");
        }

//        WechatRefundApiResult result = WechatUtil.wxRefund(orderInfo.getId().toString(),
//                orderInfo.getActual_price().doubleValue(), orderInfo.getActual_price().doubleValue());
        WechatRefundApiResult result = WechatUtil.wxRefund(orderInfo.getId().toString(),
                0.01, 0.01);
        if (result.getResult_code().equals("SUCCESS")) {
            if (orderInfo.getOrder_status() == 201) {
                orderInfo.setOrder_status(401);
            } else if (orderInfo.getOrder_status() == 300) {
                orderInfo.setOrder_status(402);
            }
            orderService.update(orderInfo);
            return toResponsSuccess("成功退款");
        } else {
            return toResponsFail("退款失败");
        }
    }


    //返回微信服务
    public static String setXml(String return_code, String return_msg) {
        return "<xml><return_code><![CDATA[" + return_code + "]]></return_code><return_msg><![CDATA[" + return_msg + "]]></return_msg></xml>";
    }

    //模拟微信回调接口
    public static String callbakcXml(String orderNum) {
        return "<xml><appid><![CDATA[wx2421b1c4370ec43b]]></appid><attach><![CDATA[支付测试]]></attach><bank_type><![CDATA[CFT]]></bank_type><fee_type><![CDATA[CNY]]></fee_type> <is_subscribe><![CDATA[Y]]></is_subscribe><mch_id><![CDATA[10000100]]></mch_id><nonce_str><![CDATA[5d2b6c2a8db53831f7eda20af46e531c]]></nonce_str><openid><![CDATA[oUpF8uMEb4qRXf22hE3X68TekukE]]></openid> <out_trade_no><![CDATA[" + orderNum + "]]></out_trade_no>  <result_code><![CDATA[SUCCESS]]></result_code> <return_code><![CDATA[SUCCESS]]></return_code><sign><![CDATA[B552ED6B279343CB493C5DD0D78AB241]]></sign><sub_mch_id><![CDATA[10000100]]></sub_mch_id> <time_end><![CDATA[20140903131540]]></time_end><total_fee>1</total_fee><trade_type><![CDATA[JSAPI]]></trade_type><transaction_id><![CDATA[1004400740201409030005092168]]></transaction_id></xml>";
    }
}